package com.hpplay.sdk.source.test.fragment;

import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.SwitchCompat;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.TextView;

import com.hpplay.sdk.source.api.ILelinkPlayerListener;
import com.hpplay.sdk.source.api.LelinkPlayerInfo;
import com.hpplay.sdk.source.api.LelinkSourceSDK;
import com.hpplay.sdk.source.browse.api.IAPI;
import com.hpplay.sdk.source.browse.api.LelinkServiceInfo;
import com.hpplay.sdk.source.test.DemoApplication;
import com.hpplay.sdk.source.test.Logger;
import com.hpplay.sdk.source.test.R;
import com.hpplay.sdk.source.test.activity.ReverseControlActivity;
import com.hpplay.sdk.source.test.config.PushConfig;
import com.hpplay.sdk.source.test.exscreen.ImageBrowseActivity;
import com.hpplay.sdk.source.test.manager.CastManager;
import com.hpplay.sdk.source.test.manager.DeviceManager;
import com.hpplay.sdk.source.test.media.MediaDataProvider;

import java.util.Objects;

public class MirrorFragment extends BaseFragment implements View.OnClickListener {
    private final static String TAG = "MirrorFragment";

    private TextView mTitleView;
    private ImageView mBackIv;
    private RadioGroup mRgResolution, mRgBitRate, mRgMirrorAudio, mRgAutoBitrate, mMirrorFullScreen,mWindowPermiss;
    private SwitchCompat mMirrorSwitch;
    private SurfaceView mSurfaceView;
    private Surface mSurface;
    private EditText mExternalVideoEt;
    private ImageView mScaleIv;
    private boolean isAutoBitrate;
    private Button mExpandBtn;
    private String mPassword;

    private LelinkServiceInfo mSelectInfo;

    private ScaleGestureDetector scaleGestureDetector;

    private final RadioGroup.OnCheckedChangeListener mBitrateChangeListener = new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {

            if (checkedId == R.id.rb_mirror_auto_bitrate_on) {
                isAutoBitrate = true;
                mRgResolution.getChildAt(0).setEnabled(false);
                mRgResolution.getChildAt(1).setEnabled(false);
                mRgResolution.getChildAt(2).setEnabled(false);
                mRgBitRate.getChildAt(0).setEnabled(false);
                mRgBitRate.getChildAt(1).setEnabled(false);
                mRgBitRate.getChildAt(2).setEnabled(false);
            } else {
                isAutoBitrate = false;
                mRgResolution.getChildAt(0).setEnabled(true);
                mRgResolution.getChildAt(1).setEnabled(true);
                mRgResolution.getChildAt(2).setEnabled(true);
                mRgBitRate.getChildAt(0).setEnabled(true);
                mRgBitRate.getChildAt(1).setEnabled(true);
                mRgBitRate.getChildAt(2).setEnabled(true);
            }
        }
    };

    private final CompoundButton.OnCheckedChangeListener onAudioCheckedChangeListener = (buttonView, isChecked) -> {
        mSurfaceView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
        mExternalVideoEt.setVisibility(isChecked ? View.VISIBLE : View.GONE);
        mScaleIv.setVisibility(isChecked ? View.INVISIBLE : View.VISIBLE);
        if (!isChecked) {
            MediaDataProvider.getInstance().stop();
            LelinkSourceSDK.getInstance().disableExternalAudio();
        } else {
            LelinkSourceSDK.getInstance().enableExternalAudio();
            MediaDataProvider.getInstance().setCallback((sampleRate, channel, audioFormat, data) ->
                    LelinkSourceSDK.getInstance().updatePCMData(sampleRate, channel, audioFormat, data, 0, data.length));
        }
    };

    private final CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            int id = compoundButton.getId();
            if (id == R.id.mirror_switch) {
                if (b) {
                    if (mSelectInfo != null) {
                        startMirror();
                    } else {
                        DemoApplication.toast("没有可镜像设备");
                    }
                } else {
                    LelinkSourceSDK.getInstance().stopPlay();
                }
            }

        }
    };

    private final ILelinkPlayerListener mMirrorListener = new ILelinkPlayerListener() {
        @Override
        public void onLoading() {
        }

        @Override
        public void onStart() {
            DemoApplication.toast("开始镜像");
            updateMirrorState();
        }

        @Override
        public void onPause() {
            DemoApplication.toast("镜像暂停");
        }

        @Override
        public void onCompletion() {
        }

        @Override
        public void onStop() {
            DemoApplication.toast("镜像停止");
            updateMirrorState();
        }

        @Override
        public void onSeekComplete(int i) {

        }

        @Override
        public void onInfo(int i, int i1) {

        }

        @Override
        public void onInfo(int what, String data) {

        }

        @Override
        public void onError(int what, int extra) {
            String text = "未知异常";
            switch (extra) {
                case EXTRA_ERROR_AUTH:
                case EXTRA_ERROR_AUTH_TIME_DONE:
                    text = "SDK认证失败";
                    break;
                case EXTRA_NEED_SCREEN_CODE:
                    text = "请输入密码";
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            showPWDDialog();
                        }
                    });
                    break;
                case EXTRA_DEVICE_OFFLINE:
                    text = "接收端不在线";
                    break;
                case EXTRA_ERROR_MIRROR_REQUEST_PERMISSION:
                    text = "申请录屏权限发生异常";
                    break;
                case EXTRA_ERROR_MIRROR_REJECT_PERMISSION:
                    text = "申请录屏权限被拒绝";
                    break;
                case EXTRA_ERROR_MIRROR_DEVICE_UNSUPPORTED:
                    text = "此设备不支持镜像";
                    break;
                case EXTRA_ERROR_MIRROR_IO:
                    text = "网络通讯异常";
                    break;
                case EXTRA_ERROR_MIRROR_UNSUPPORTED:
                    text = "SDK不支持镜像";
                    break;
                case EXTRA_ERROR_MIRROR_SINK_UNSUPPORTED:
                    text = "接收端不支持此镜像";
                    break;
                case EXTRA_ERROR_MIRROR_INVALID_INPUT:
                    text = "输入异常";
                    break;
            }
            if (TextUtils.isEmpty(text)) {
                text = "镜像 onError " + what + "/" + extra;
            }
            DemoApplication.toast(text);
            updateMirrorState();
        }

        @Override
        public void onVolumeChanged(float v) {

        }

        @Override
        public void onPositionUpdate(long duration, long position) {

        }
    };

    @Override
    public int getLayoutID() {
        return R.layout.f_mirror;
    }

    @Override
    public void init(View view) {
        initView(view);
    }

    private void initView(View view) {
        Logger.i(TAG, "initView");
        mTitleView = view.findViewById(R.id.title);
        mBackIv = view.findViewById(R.id.iv_back);
        mBackIv.setOnClickListener(this);
        mRgResolution = view.findViewById(R.id.rg_resolution);
        mRgBitRate = view.findViewById(R.id.rg_bitrate);
        mRgMirrorAudio = view.findViewById(R.id.rg_mirror_audio);
        mRgAutoBitrate = view.findViewById(R.id.rg_auto_bitrate);
        mMirrorFullScreen = view.findViewById(R.id.rg_full_screen);
        mMirrorFullScreen.check(R.id.rb_mirror_full_screen_auto);
        mWindowPermiss = view.findViewById(R.id.mindow_permiss);
        mWindowPermiss.check(R.id.mindow_permiss_on);
        mMirrorSwitch = view.findViewById(R.id.mirror_switch);
        SwitchCompat customAudioSwitch = view.findViewById(R.id.custom_audio_switch);
        customAudioSwitch.setChecked(false);
        customAudioSwitch.setOnCheckedChangeListener(onAudioCheckedChangeListener);
        view.findViewById(R.id.btn_pause_mirror).setOnClickListener(this);
        view.findViewById(R.id.btn_resume_mirror).setOnClickListener(this);
        mExpandBtn = view.findViewById(R.id.btn_expan);
        mExpandBtn.setOnClickListener(this);
        view.findViewById(R.id.btn_reverse_control).setOnClickListener(this);

        mRgAutoBitrate.setOnCheckedChangeListener(mBitrateChangeListener);
        if (mSelectInfo != null) {
            mTitleView.setText(mSelectInfo.getName());
        }

        mExternalVideoEt = view.findViewById(R.id.et_external_video_path);
        mExternalVideoEt.setText(PushConfig.getInstance().getExternalVideo());
        initSurface(view);

        mScaleIv = view.findViewById(R.id.iv_scale);
        ScaleGestureDetector detector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                Logger.i(TAG, "onScale: ");
                mScaleIv.setScaleX(mScaleIv.getScaleX() * detector.getScaleFactor());
                mScaleIv.setScaleY(mScaleIv.getScaleY() * detector.getScaleFactor());
                return true;
            }

            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                return true;
            }

            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {

            }
        });
        mScaleIv.setOnTouchListener((v, event) -> {
            Logger.i(TAG, "onTouchEvent: event: " + event.toString());
            return detector.onTouchEvent(event);
        });
        setSinkTouchEventListener();
    }

    private void setSinkTouchEventListener() {
        if (scaleGestureDetector == null) {
            scaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {
                @Override
                public boolean onScale(ScaleGestureDetector detector) {
                    mScaleIv.setScaleX(mScaleIv.getScaleX() * detector.getScaleFactor());
                    mScaleIv.setScaleY(mScaleIv.getScaleY() * detector.getScaleFactor());
                    return true;
                }

                @Override
                public boolean onScaleBegin(ScaleGestureDetector detector) {
                    return true;
                }

                @Override
                public void onScaleEnd(ScaleGestureDetector detector) {

                }
            });
        }

        mScaleIv.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Logger.i(TAG, "onTouch: event: " + event);
                return scaleGestureDetector.onTouchEvent(event);
            }
        });
    }

    private void initSurface(View view) {
        mSurfaceView = view.findViewById(R.id.surface_view);
        mSurfaceView.getHolder().addCallback(callback2);
        mSurfaceView.setOnClickListener(v -> {
            MediaDataProvider.getInstance().start(mSurface, PushConfig.getInstance().getExternalVideo());
        });
    }

    SurfaceHolder.Callback2 callback2 = new SurfaceHolder.Callback2() {
        @Override
        public void surfaceRedrawNeeded(SurfaceHolder holder) {

        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            Logger.i(TAG, "surfaceCreated: ");
            mSurface = holder.getSurface();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }
    };

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        updateMirrorState();
        CastManager.getInstance().addPlayerListener(mMirrorListener);
        setSelectInfo(DeviceManager.getInstance().getSelectInfo());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_pause_mirror:
                LelinkSourceSDK.getInstance().pause();
                break;
            case R.id.btn_resume_mirror:
                LelinkSourceSDK.getInstance().resume();
                break;
            case R.id.btn_expan:
                Intent intent = new Intent(getActivity(), ImageBrowseActivity.class);
                intent.putExtra("serviceinfo", mSelectInfo);
                startActivity(intent);
                break;
            case R.id.btn_reverse_control:
                ReverseControlActivity.show(Objects.requireNonNull(getContext()));
                break;
            case R.id.iv_back:
                getActivity().getSupportFragmentManager().beginTransaction()
                        .remove(this)
                        .commitAllowingStateLoss();
                break;
        }
    }

    public void setSelectInfo(LelinkServiceInfo info) {
        mSelectInfo = info;
        if (mTitleView != null && mSelectInfo != null) {
            mTitleView.setText(mSelectInfo.getName());
        }
        LelinkSourceSDK.getInstance().connect(info);
    }

    public void updateMirrorState() {
        DemoApplication.runOnUI(() -> {
            mMirrorSwitch.setOnCheckedChangeListener(null);
            mMirrorSwitch.setChecked(isMirroring());
            mMirrorSwitch.setOnCheckedChangeListener(onCheckedChangeListener);
        });
    }

    private boolean isMirroring() {
        Object mirrorState = LelinkSourceSDK.getInstance().getOption(IAPI.OPTION_32);
        return mirrorState instanceof Integer && ((int) mirrorState == LelinkSourceSDK.MIRROR_PLAYING || (int) mirrorState == LelinkSourceSDK.MIRROR_PAUSE);
    }

    private void startMirror() {
        if (mSelectInfo == null) {
            DemoApplication.toast("请选择设备!");
            return;
        }
        // 分辨率
        int resolutionLevel = 0;
        int resolutionCheckId = mRgResolution.getCheckedRadioButtonId();
        switch (resolutionCheckId) {
            case R.id.rb_resolution_height:
                resolutionLevel = LelinkSourceSDK.RESOLUTION_HIGH;
                break;
            case R.id.rb_resolution_middle:
                resolutionLevel = LelinkSourceSDK.RESOLUTION_MIDDLE;
                break;
            case R.id.rb_resolution_low:
                resolutionLevel = LelinkSourceSDK.RESOLUTION_AUTO;
                break;
        }

        // 比特率
        int bitrateLevel = 0;
        int bitrateCheckId = mRgBitRate.getCheckedRadioButtonId();
        switch (bitrateCheckId) {
            case R.id.rb_bitrate_height:
                bitrateLevel = LelinkSourceSDK.BITRATE_HIGH;
                break;
            case R.id.rb_bitrate_middle:
                bitrateLevel = LelinkSourceSDK.BITRATE_MIDDLE;
                break;
            case R.id.rb_bitrate_low:
                bitrateLevel = LelinkSourceSDK.BITRATE_LOW;
                break;
        }
        // 音频
        boolean audioEnable = true;
        int audioCheckId = mRgMirrorAudio.getCheckedRadioButtonId();
        switch (audioCheckId) {
            case R.id.rb_mirror_audio_on:
                audioEnable = true;
                break;
            case R.id.rb_mirror_audio_off:
                audioEnable = false;
                break;
        }
        // 全屏镜像
        int fullScreen = LelinkPlayerInfo.FULLSCREEN_AUTO;
        switch (mMirrorFullScreen.getCheckedRadioButtonId()) {
            case R.id.rb_mirror_full_screen_auto:
                fullScreen = LelinkPlayerInfo.FULLSCREEN_AUTO;
                break;
            case R.id.rb_mirror_full_screen_on:
                fullScreen = LelinkPlayerInfo.FULLSCREEN_ON;
                break;
            case R.id.rb_mirror_full_screen_off:
                fullScreen = LelinkPlayerInfo.FULLSCREEN_OFF;
                break;
        }

        // 悬浮窗权限申请
        int windowCheckId = mWindowPermiss.getCheckedRadioButtonId();
        switch (windowCheckId) {
            case R.id.mindow_permiss_on:
                LelinkSourceSDK.getInstance().setOverlayPermission(1);
                break;
            case R.id.mindow_permiss_off:
                LelinkSourceSDK.getInstance().setOverlayPermission(0);
                break;
        }

        //两种方法都可镜像
        LelinkPlayerInfo lelinkPlayerInfo = new LelinkPlayerInfo();
        lelinkPlayerInfo.setAutoBitrate(isAutoBitrate);
        lelinkPlayerInfo.setLelinkServiceInfo(mSelectInfo);
        lelinkPlayerInfo.setBitRateLevel(bitrateLevel);
        lelinkPlayerInfo.setResolutionLevel(resolutionLevel);
        if (!TextUtils.isEmpty(mPassword)) {
            lelinkPlayerInfo.setCastPwd(mPassword);
        }
        lelinkPlayerInfo.setMirrorAudioEnable(audioEnable);
        lelinkPlayerInfo.setFullScreen(fullScreen);
        if (mSurfaceView.getVisibility() == View.VISIBLE) {
            LelinkSourceSDK.getInstance().enableExternalAudio();
        } else {
            LelinkSourceSDK.getInstance().disableExternalAudio();
        }
        LelinkSourceSDK.getInstance().startMirror(lelinkPlayerInfo);
    }

    public void showPWDDialog() {
        final EditText editText = new EditText(getActivity());
        new AlertDialog.Builder(getActivity()).setTitle("请输入密码")
                .setView(editText)
                .setPositiveButton("确定", (diaLoggerInterface, i) -> {
                    if (TextUtils.isEmpty(editText.getText().toString())) {
                        DemoApplication.toast("请输入密码");
                        return;
                    }
                    mPassword = editText.getText().toString();
                    if (!mMirrorSwitch.isChecked()) {
                        mMirrorSwitch.setChecked(true);
                    } else {
                        startMirror();
                    }
                }).setNegativeButton("取消", null).show();
    }

    @Override
    public void onDestroyView() {
        CastManager.getInstance().removeListener(mMirrorListener);
        mSurfaceView.getHolder().removeCallback(callback2);
        MediaDataProvider.getInstance().stop();
        super.onDestroyView();
    }
}
